﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel;
using System.Reflection;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;
using Cherry.Agile.ServiceModel.Runtime.Instrumentation;

namespace Cherry.Agile.ServiceModel.Interceptor
{
    sealed class ErrorHandler : IErrorHandler
    {
        public string ExceptionPolicyName
        { get; private set; }
        public ErrorHandler(string exceptionPolicyName)
        {
            if (string.IsNullOrEmpty(exceptionPolicyName))
            {
                throw new ArgumentNullException("exceptionPolicyName");
            }
            this.ExceptionPolicyName = exceptionPolicyName;
        }

        #region IErrorHandler Members

        public bool HandleError(Exception error)
        {
            return false;
        }

        public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
        {
            if (typeof(FaultException).IsInstanceOfType(error))
            {
                return;
            }

            try
            {
                if (ExceptionPolicy.HandleException(error, this.ExceptionPolicyName))
                {
                    fault = Message.CreateMessage(version, BuildFault(error), FaultMessage.FaultAction);
                }
            }
            catch (Exception ex)
            {
                fault = Message.CreateMessage(version, BuildFault(ex), FaultMessage.FaultAction);
            }
        }

        private MessageFault BuildFault(Exception error)
        {
            Instrumentation.Error();
            if (error.GetType().Name == "MySqlException")
                error = new System.Exception("db connection error:" + error.Message);
            FaultMessage exceptionDetail = new FaultMessage(error);
            return MessageFault.CreateFault(FaultCode.CreateReceiverFaultCode(FaultMessage.FaultSubCodeName, FaultMessage.FaultSubCodeNamespace),
                new FaultReason(error.Message), exceptionDetail);
        }

        #endregion
    }

}
